﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using log4net;
using Microsoft.Synchronization.Data;
using System.Data.SqlClient;
using SyncLib.Data;
using Microsoft.Synchronization;
using System.Collections;
using System.ServiceModel;
using System.Threading;
using SyncLib.Client;
using System.IO;

namespace SyncLib.Provider
{
    public class ClientComplexSync2 : BaseKeeperSync
    {
        ILog Log = LogManager.GetLogger(typeof(Log4NetImplement));
        protected override void OnChangesSelected(DbChangesSelectedEventArgs e)
        {
            try
            {
                base.OnChangesSelected(e);
                Transaction = (SqlTransaction)e.Transaction;
                MonitorEvent.Monitor.Info("Lấy dữ liệu từ bảng con");
                SelectDependencyData(e);

            }
            finally
            {
                Transaction = null;
            }
        }
        protected override void OnSyncProgress(DbSyncProgressEventArgs e)
        {
            try
            {
                Log.Debug(
                         string.Format("SessionId={0} {1} SyncProgress: State={2} Table ={3} Rowindex={4}/Count={5}",
                         SessionId, Context.CurrentScope.ScopeName, e.Stage, e.TableProgress.TableName, e.TableProgress.RowIndex, e.TableProgress.DataTable.Rows.Count));

                switch (e.Stage)
                {
                    case DbSyncStage.ApplyingDeletes:
                    case DbSyncStage.ApplyingInserts:
                    case DbSyncStage.ApplyingUpdates:
                        {

                            if (e.TableProgress.DataTable.Rows.Count > e.TableProgress.RowIndex)
                            {
                                DataView view = new DataView(e.TableProgress.DataTable);
                                view.RowStateFilter = DataViewRowState.CurrentRows | DataViewRowState.Deleted;
                                DataRowView rowView = view[e.TableProgress.RowIndex];
                                if (!rowView.Row.Equals(e.TableProgress.DataTable.Rows[e.TableProgress.RowIndex]))
                                {
                                    Log.Info("RowIndex not match dataview--> Manunal localtion rowview");
                                    rowView = null;

                                    foreach (DataRowView rowv in view)
                                        if (rowv.Row.Equals(e.TableProgress.DataTable.Rows[e.TableProgress.RowIndex]))
                                        {
                                            rowView = rowv;
                                            break;
                                        }
                                }
                                MonitorEvent.Monitor.Info(string.Format("Lưu thay đổi bảng con {0} {1}/{2}", e.TableProgress.TableName, e.TableProgress.RowIndex + 1, e.TableProgress.DataTable.Rows.Count));
                                ApplyDependencyTables(rowView, e);


                            }
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                Log.Fatal(
                   string.Format("SessionId={0} {1} SyncProgress: State={2} Table ={3} Rowindex={4}",
                   SessionId, Context.CurrentScope.ScopeName, e.Stage, e.TableProgress.TableName, e.TableProgress.RowIndex),
                       ex);
                
                throw ex;
            }
        }


        private void SelectDependencyData(Microsoft.Synchronization.Data.DbChangesSelectedEventArgs e)
        {
            foreach (DataTable tblData in e.Context.DataSet.Tables)
            {

                SelectDependencyData(tblData.TableName, e);
            }
        }

        void SelectDependencyData(string tableName, DbChangesSelectedEventArgs e)
        {
            string debugStep = "Unknown";
            try
            {
                Log.Info("GetDependencyData for table " + tableName);
                TableOfScope tos = _SyncContext.CurrentScope.FindTable(tableName);
                if (tos != null)
                {
                    _SyncContext.CurrentTable = tos;
                    if (tos.DependencyTables.Length > 0)
                    {
                        DataView view = new DataView(e.Context.DataSet.Tables[tableName]);
                        view.RowStateFilter = DataViewRowState.CurrentRows | DataViewRowState.Deleted;

                        for (int rowIndex = 0; rowIndex < view.Count; rowIndex++)
                        {
                            MonitorEvent.Monitor.Info(string.Format("{2}({0}/{1}) ", rowIndex + 1, view.Count, tableName));
                            debugStep = "Get primary columns values of processRow";
                            string[] primaryColumns = tos.GetPrimaryColumns();
                            List<string> primaryValues = new List<string>();
                            for (int i = 0; i < primaryColumns.Length; i++)
                            {
                                primaryValues.Add(view[rowIndex][primaryColumns[i]].ToString());
                            }
                            string[] arrPrimaryValues = primaryValues.ToArray();
                            primaryValues.Clear();
                            primaryValues = null;

                            KDataBatchProducer batchProducer = new KDataBatchProducer(tableName, Connection, Transaction, ClientId, _SyncContext.Position.ToString());
                            batchProducer.BatchSize = _SyncContext.CurrentScope.BatchSize;
                            batchProducer.BatchDirectory = CommonVariable.SyncFolderBatch + "\\" + ClientId.ToString();
                            batchProducer.DelegateSerializeBatch = new SerializeBatch(UploadDependencyData);
                            string dataKey = KeeperSyncUtility.CreateDependencyKey(tos.TableName, rowIndex, arrPrimaryValues);
                            batchProducer.PrefixFileName = dataKey;
                            for (int i = 0; i < tos.DependencyTables.Length; i++)
                            {

                                DependencyTable childrenTable = tos.DependencyTables[i];
                                _SyncContext.CurrentDepen = childrenTable;
                                //  MonitorEvent.Monitor.Info(string.Format("{2}({0}/{1})==> ", rowIndex + 1, view.Count, tableName, childrenTable.TableName));

                                SelectDependencyData(childrenTable, view[rowIndex], e, batchProducer);
                                debugStep = "Upload DependencyData";
                                // UploadKDataBatchHandle(dataKey, batchHandle);
                                _SyncContext.CurrentDepen = null;
                            }
                            batchProducer.EndBatchProducer();
                        }
                    }
                }
                Log.Info("End GetDependencyData for table " + tableName);
            }
            catch (Exception ex)
            {
                Log.Fatal("End GetDependencyData for table " + tableName + " with exception(" + debugStep + "):", ex);
                if (_Transaction != null)
                    _Transaction.Rollback();
                throw ex;
            }
            finally
            {
                _SyncContext.CurrentTable = null;
                _SyncContext.CurrentDepen = null;
            }
        }
        void SelectDependencyData(DependencyTable childrenTable, DataRowView currentRow, DbChangesSelectedEventArgs e, KDataBatchProducer batchProducer)
        {
            Log.InfoFormat(" Select dependency rows of table {0} in table {1}", _SyncContext.CurrentTable.TableName, childrenTable.TableName);

            using (SqlCommand command = new SqlCommand(childrenTable.SelectRowCommand, Connection, Transaction))
            {
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.AddRange(
                    SqlHelperParameterCache.GetSpParameterSet(CommonVariable.SqlConnectionString,
                            command.CommandText)
                    );
                KeeperSyncUtility.AssignParameterValues(command, currentRow, DbSyncStage.SelectingChanges, Context);
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    batchProducer.AddReader(reader, childrenTable.TableName);

                }
            }
        }

        void UploadDependencyData(KDataBatch batch)
        {
            int i = 0;
            while (i < 2)
                try
                {
                    ProxyInfo.Channel.UploadDependencyData(batch);
                    break;
                }
                catch (Exception ex)
                {
                    Log.Fatal(string.Format("UploadDependencyData({0}) =>", i), ex);
                    if (i < 2)
                        i++;
                    else
                        throw ex;
                }
        }
        KDataBatch DownloadDependencyData(string fileName)
        {
            int i = 0;
            while (i < 2)
                try
                {
                    return ProxyInfo.Channel.DownloadDependencyData(fileName);
                }
                catch (Exception ex)
                {
                    Log.Fatal(string.Format("DownloadDependencyData({0}) =>", i), ex);
                    if (i < 2)
                        i++;
                    else
                        throw ex;
                }
            return null;

        }

        void ApplyDependencyTables(DataRowView processRow, DbSyncProgressEventArgs e)
        {
            string debugStep = "Unknown";
            try
            {
                debugStep = "Find TableOfScope";
                TableOfScope tos = _SyncContext.CurrentScope.FindTable(e.TableProgress.TableName);
                if (tos == null)
                {
                    Log.WarnFormat("ApplyDependencyTables[Skipped] TableOfScope {0} not found in {1}",
                        e.TableProgress.TableName, _SyncContext.CurrentScope.ScopeName);
                    return;
                }
                _SyncContext.CurrentTable = tos;

                debugStep = "Get primary columns values of processRow";
                string[] primaryColumns = tos.GetPrimaryColumns();
                List<string> primaryValues = new List<string>();
                for (int i = 0; i < primaryColumns.Length; i++)
                {
                    primaryValues.Add(processRow[primaryColumns[i]].ToString());
                }
                string[] arrPrimaryValues = primaryValues.ToArray();
                primaryValues.Clear();
                primaryValues = null;

                foreach (DependencyTable detailTable in tos.DependencyTables)
                {
                    _SyncContext.CurrentDepen = detailTable;
                    KeeperSyncUtility.DeTPreApplyTableCommand(processRow, e.Stage, this);
                }

                string fileKey = KeeperSyncUtility.CreateDependencyKey(tos.TableName, e.TableProgress.RowIndex, arrPrimaryValues);
                int fileIndex = 0;
                KDataBatch batch = DownloadDependencyData(fileKey + "_" + fileIndex.ToString() + ".depen");
                while (batch != null)
                {

                    DataSet depenData = batch.DataSetSurrogate.ConvertToDataSet();
                    foreach (DataTable table in depenData.Tables)
                    {
                        if (table.Rows.Count > 0)
                        {
                            _SyncContext.CurrentDepen = tos.FindDependency(table.TableName);
                            int count = KeeperSyncUtility.DeTCallApplyRowCommand(table, e.Stage, this);
                            DbSyncTableProgress tableProcess = null;
                            if (DependencyStatistic.ContainsKey(tos.TableName))
                            {
                                DbSyncScopeProgress tosProcesss = DependencyStatistic[tos.TableName];
                                tableProcess = tosProcesss.FindTableProgress(_SyncContext.CurrentDepen.TableName);

                                if (tableProcess == null)
                                {
                                    tableProcess = new DbSyncTableProgress(_SyncContext.CurrentDepen.TableName);
                                    tosProcesss.TablesProgress.Add(tableProcess);
                                }
                            }
                            else
                            {
                                DbSyncScopeProgress tosProcess = new DbSyncScopeProgress();
                                tableProcess = new DbSyncTableProgress(_SyncContext.CurrentDepen.TableName);
                                tosProcess.TablesProgress.Add(tableProcess);
                                DependencyStatistic.Add(tos.TableName, tosProcess);
                            }
                            tableProcess.ChangesApplied += count;
                            tableProcess.Inserts += count;
                            Log.DebugFormat("        End apply batch {0}. Total applie {1}", fileIndex, count);
                        }
                        _SyncContext.CurrentDepen = null;
                    }
                    fileIndex++;
                    batch = DownloadDependencyData(fileKey + "_" + fileIndex.ToString() + ".depen");
                }

                KeeperSyncUtility.TOSAfterApplyCommand(processRow, e.Stage, this);
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("ApplyDependencyTables {0}\n {1} \n[Step info]{2}",
                        e.TableProgress.TableName, _SyncContext.GetCurrentInfo(), debugStep), ex);
            }
            finally
            {
                _SyncContext.CurrentTable = null;
                _SyncContext.CurrentDepen = null;
            }

        }
    }

    //public class ClientComplexSync : BaseKeeperSync
    //{
    //    ILog Log = LogManager.GetLogger(typeof(Log4NetImplement));
    //    List<string> appliedKey = null;
    //    public ClientComplexSync()
    //        : base()
    //    {
    //        appliedKey = new List<string>();
    //    }
    //    protected override void OnChangesSelected(DbChangesSelectedEventArgs e)
    //    {
    //        try
    //        {
    //            base.OnChangesSelected(e);
    //            Transaction = (SqlTransaction)e.Transaction;
    //            MonitorEvent.Monitor.Info("Lấy dữ liệu phụ thuộc");
    //          SelectDependencyData(e);

    //        }
    //        finally
    //        {
    //            Transaction = null;
    //        }
    //    }
    //    protected override void OnSyncProgress(DbSyncProgressEventArgs e)
    //    {
    //        try
    //        {
    //            Log.Debug(
    //                     string.Format("SessionId={0} {1} SyncProgress: State={2} Table ={3} Rowindex={4}/Count={5}",
    //                     SessionId, Context.CurrentScope.ScopeName, e.Stage, e.TableProgress.TableName, e.TableProgress.RowIndex, e.TableProgress.DataTable.Rows.Count));
    //            //if (e.TableProgress.RowIndex % 20 == 0)
    //            //    KeepAlive();
    //            switch (e.Stage)
    //            {
    //                case DbSyncStage.ApplyingDeletes:
    //                case DbSyncStage.ApplyingInserts:
    //                case DbSyncStage.ApplyingUpdates:
    //                    {
    //                        //if (e.TableProgress.DataTable.Rows.Count > e.TableProgress.RowIndex)
    //                        //{
    //                        //DataRowView rowView = e.TableProgress.DataTable.DefaultView[e.TableProgress.RowIndex];
    //                        //if (!rowView.Row.Equals(e.TableProgress.DataTable.Rows[e.TableProgress.RowIndex]))
    //                        //{
    //                        //    rowView = null;
    //                        //    foreach (DataRowView rowv in e.TableProgress.DataTable.DefaultView)
    //                        //        if (rowv.Row.Equals(e.TableProgress.DataTable.Rows[e.TableProgress.RowIndex]))
    //                        //        {
    //                        //            rowView = rowv;
    //                        //            break;
    //                        //        }
    //                        //}

    //                        if (e.TableProgress.DataTable.Rows.Count > e.TableProgress.RowIndex)
    //                        {
    //                            DataView view = new DataView(e.TableProgress.DataTable);
    //                            view.RowStateFilter = DataViewRowState.CurrentRows | DataViewRowState.Deleted;
    //                            DataRowView rowView = view[e.TableProgress.RowIndex];
    //                            if (!rowView.Row.Equals(e.TableProgress.DataTable.Rows[e.TableProgress.RowIndex]))
    //                            {
    //                                Log.Info("RowIndex not match dataview--> Manunal localtion rowview");
    //                                rowView = null;

    //                                foreach (DataRowView rowv in view)
    //                                    if (rowv.Row.Equals(e.TableProgress.DataTable.Rows[e.TableProgress.RowIndex]))
    //                                    {
    //                                        rowView = rowv;
    //                                        break;
    //                                    }
    //                            }
    //                            MonitorEvent.Monitor.Info(string.Format("Lưu thay đổi bảng con {0} {1}/{2}", e.TableProgress.TableName, e.TableProgress.RowIndex + 1, e.TableProgress.DataTable.Rows.Count));
    //                            ApplyDependencyTables(rowView, e);


    //                        }
    //                    }
    //                    break;
    //            }
    //        }
    //        catch (Exception ex)
    //        {
    //            Log.Fatal(
    //               string.Format("SessionId={0} {1} SyncProgress: State={2} Table ={3} Rowindex={4}",
    //               SessionId, Context.CurrentScope.ScopeName, e.Stage, e.TableProgress.TableName, e.TableProgress.RowIndex),
    //                   ex);
    //            throw ex;
    //        }
    //    }

    //    void ApplyDependencyTables2(DataRowView processRow, DbSyncProgressEventArgs e)
    //    {
    //    }

    //    void ApplyDependencyTables(DataRowView processRow, DbSyncProgressEventArgs e)
    //    {
    //        string debugStep = "Unknown";
    //        try
    //        {
    //            debugStep = "Find TableOfScope";
    //            TableOfScope tos = _SyncContext.CurrentScope.FindTable(e.TableProgress.TableName);
    //            if (tos == null)
    //            {
    //                Log.WarnFormat("ApplyDependencyTables[Skipped] TableOfScope {0} not found in {1}",
    //                    e.TableProgress.TableName, _SyncContext.CurrentScope.ScopeName);
    //                return;
    //            }
    //            _SyncContext.CurrentTable = tos;

    //            debugStep = "Get primary columns values of processRow";
    //            string[] primaryColumns = tos.GetPrimaryColumns();
    //            List<string> primaryValues = new List<string>();
    //            for (int i = 0; i < primaryColumns.Length; i++)
    //            {
    //                primaryValues.Add(processRow[primaryColumns[i]].ToString());
    //            }
    //            string[] arrPrimaryValues = primaryValues.ToArray();
    //            primaryValues.Clear();
    //            primaryValues = null;
    //            KDataBatchHandle batchHandle = null;
    //            foreach (DependencyTable detailTable in tos.DependencyTables)
    //            {
    //                _SyncContext.CurrentDepen = detailTable;
    //                KeeperSyncUtility.DeTPreApplyTableCommand(processRow, e.Stage, this);
    //                Log.Info("Begin apply dependency  Table \"" + detailTable.TableName + "\"");
    //                debugStep = "Create Download key for table " + detailTable.TableName;
    //                string downloadKey = KeeperSyncUtility.CreateDependencyKey(
    //                      tos.TableName, detailTable.TableName, e.TableProgress.RowIndex, arrPrimaryValues);
    //                if (appliedKey.Contains(downloadKey))
    //                {
    //                    Log.WarnFormat("    Found DownloadKey=\"{0}\" in Applied Keys List==> Skipped", downloadKey);
    //                    _SyncContext.CurrentDepen = null;
    //                    continue;
    //                }
    //                debugStep = "Download KDataBatchHandle";
    //                if (_SyncContext.Position == SyncProviderPosition.Local)
    //                {
    //                    //Using Proxy to download DependencyData
    //                    if (Proxy == null)
    //                        throw new Exception("Proxy is null");


    //                    batchHandle = DownloadDataBatchHandleFromProxy(downloadKey);
    //                }
    //                else//Remote Position
    //                {
    //                    //Using Session Manager to Access DenpendencyData
    //                    Log.Info("  Access IKeeperSync to get KDataBatchHandle with key:" + downloadKey);
    //                    batchHandle = UploadedDependencyData[downloadKey];
    //                }

    //                if (batchHandle == null)
    //                    throw new Exception(string.Format("KDataBatchHandle not found on {0} SessionManager", _SyncContext.Position));
    //                Log.InfoFormat("      Download KDataBatchHandle success: Total Batch={0}", batchHandle.TotalBatch);
    //                debugStep = " Apply Batch Data";

    //                for (int i = 1; i <= batchHandle.TotalBatch; i++)
    //                {
    //                    Log.DebugFormat("        Begin apply batch {0} of {1}", i, batchHandle.TotalBatch);
    //                    KDataBatch batch = GetDataBatch4Apply(i, downloadKey);
    //                    int count = KeeperSyncUtility.DeTCallApplyRowCommand(batch.Data.Tables[0], e.Stage, this);

    //                    //Statictis
    //                    DbSyncTableProgress tableProcess = null;
    //                    if (DependencyStatistic.ContainsKey(tos.TableName))
    //                    {
    //                        DbSyncScopeProgress tosProcesss = DependencyStatistic[tos.TableName];
    //                        tableProcess = tosProcesss.FindTableProgress(detailTable.TableName);

    //                        if (tableProcess == null)
    //                        {
    //                            tableProcess = new DbSyncTableProgress(detailTable.TableName);
    //                            tosProcesss.TablesProgress.Add(tableProcess);
    //                        }
    //                    }
    //                    else
    //                    {
    //                        DbSyncScopeProgress tosProcess = new DbSyncScopeProgress();
    //                        tableProcess = new DbSyncTableProgress(detailTable.TableName);
    //                        tosProcess.TablesProgress.Add(tableProcess);
    //                        DependencyStatistic.Add(tos.TableName, tosProcess);
    //                    }
    //                    tableProcess.ChangesApplied += count;
    //                    tableProcess.Inserts += count;
    //                    appliedKey.Add(downloadKey);
    //                    Log.DebugFormat("        End apply batch {0}. Total applie {1}", i, count);
    //                }
    //                Log.DebugFormat("End apply dependency table \"" + detailTable.TableName + "\"");
    //                _SyncContext.CurrentDepen = null;
    //            }

    //            KeeperSyncUtility.TOSAfterApplyCommand(processRow, e.Stage, this);
    //        }
    //        catch (Exception ex)
    //        {
    //            throw new Exception(string.Format("ApplyDependencyTables {0}\n {1} \n[Step info]{2}",
    //                    e.TableProgress.TableName, _SyncContext.GetCurrentInfo(), debugStep), ex);
    //        }
    //        finally
    //        {
    //            _SyncContext.CurrentTable = null;
    //            _SyncContext.CurrentDepen = null;
    //        }

    //    }
    //    KDataBatchHandle DownloadDataBatchHandleFromProxy(string downloadKey)
    //    {
    //        int tryCount = 0;
    //        while (tryCount < 3)
    //        {
    //            try
    //            {
    //                return Proxy.DownloadDependencyBatchInfo(downloadKey);
    //            }
    //            catch (FaultException<WebSyncFaultException> wfe)
    //            {
    //                Log.FatalFormat("Try DownloadDataBatchHandle({0}) has FaultException<WebSyncFaultException>{1}",
    //                   (tryCount + 1), wfe.Detail.Message + wfe.InnerException);

    //                tryCount++;
    //                if (tryCount == 3)
    //                    throw wfe;
    //                Thread.Sleep(1000);
    //            }
    //            catch (CommunicationException ce)
    //            {

    //                Log.Fatal(string.Format("Try DownloadDataBatchHandle({0}) has CommunicationException",
    //                   (tryCount + 1)), ce);
    //                tryCount++;
    //                if (tryCount == 3)
    //                    throw ce;
    //                Thread.Sleep(1000);
    //            }
    //            catch (Exception ex)
    //            {
    //                tryCount = 3;
    //                throw new Exception("End DownloadDataBatchHandle with exception ", ex);
    //            }
    //        }
    //        return null;
    //    }
    //    KDataBatch GetDataBatch4Apply(int index, string downloadKey)
    //    {
    //        if (_SyncContext.Position == SyncProviderPosition.Local)
    //        {
    //            return DownloadDataBatch(index, downloadKey);
    //        }
    //        else
    //        {
    //            Log.InfoFormat("            Access IKeeperSync to load DataBatch index {0}", index);
    //            return UploadedDependencyData[downloadKey].AllBatch[index];
    //        }
    //    }
    //    KDataBatch DownloadDataBatch(int index, string downloadKey)
    //    {
    //        int tryCount = 0;
    //        Log.InfoFormat("            Try DownloadDataBatch with Index {0} Key \"{1}\"", index, downloadKey);
    //        while (tryCount < 3)
    //        {
    //            try
    //            {
    //                return Proxy.DownloadDependencyData(downloadKey, index);
    //            }
    //            catch (FaultException<WebSyncFaultException> wfe)
    //            {
    //                Log.FatalFormat("           Try DownloadDataBatch({0}) has FaultException<WebSyncFaultException>{1}",
    //                   (tryCount + 1), wfe.Detail.Message + wfe.InnerException);

    //                tryCount++;
    //                if (tryCount == 3)
    //                    throw wfe;
    //                Thread.Sleep(1000);
    //            }
    //            catch (CommunicationException ce)
    //            {

    //                Log.Fatal(string.Format("           Try DownloadDataBatch({0}) has CommunicationException",
    //                   (tryCount + 1)), ce);
    //                tryCount++;
    //                if (tryCount == 3)
    //                    throw ce;
    //                Thread.Sleep(1000);
    //            }
    //            catch (Exception ex)
    //            {
    //                tryCount = 3;
    //                throw new Exception("           End DownloadDataBatch with exception ", ex);
    //            }
    //        }
    //        return null;
    //    }
    //    void SelectDependencyData(DbChangesSelectedEventArgs e)
    //    {
    //        foreach (DataTable tblData in e.Context.DataSet.Tables)
    //            SelectDependencyData(tblData.TableName, e);
    //    }
    //    void SelectDependencyData(string tableName, DbChangesSelectedEventArgs e)
    //    {
    //        string debugStep = "Unknown";
    //        try
    //        {
    //            Log.Info("GetDependencyData for table " + tableName);
    //            TableOfScope tos = _SyncContext.CurrentScope.FindTable(tableName);
    //            if (tos != null)
    //            {
    //                _SyncContext.CurrentTable = tos;
    //                if (tos.DependencyTables.Length > 0)
    //                {
    //                    DataView view = new DataView(e.Context.DataSet.Tables[tableName]);
    //                    view.RowStateFilter = DataViewRowState.CurrentRows | DataViewRowState.Deleted;

    //                    for (int rowIndex = 0; rowIndex < view.Count; rowIndex++)
    //                    {
    //                        MonitorEvent.Monitor.Info(string.Format("{2}({0}/{1}) ", rowIndex + 1, view.Count, tableName));
    //                        debugStep = "Get primary columns values of processRow";
    //                        string[] primaryColumns = tos.GetPrimaryColumns();
    //                        List<string> primaryValues = new List<string>();
    //                        for (int i = 0; i < primaryColumns.Length; i++)
    //                        {
    //                            primaryValues.Add(view[rowIndex][primaryColumns[i]].ToString());
    //                        }
    //                        string[] arrPrimaryValues = primaryValues.ToArray();
    //                        primaryValues.Clear();
    //                        primaryValues = null;

    //                        for (int i = 0; i < tos.DependencyTables.Length; i++)
    //                        {

    //                            DependencyTable childrenTable = tos.DependencyTables[i];
    //                            _SyncContext.CurrentDepen = childrenTable;
    //                            MonitorEvent.Monitor.Info(string.Format("{2}({0}/{1})==> ", rowIndex + 1, view.Count, tableName, childrenTable.TableName));
    //                            string dataKey = KeeperSyncUtility.CreateDependencyKey(tos.TableName, childrenTable.TableName, rowIndex, arrPrimaryValues);
    //                            KDataBatchHandle batchHandle = SelectDependencyData(childrenTable, view[rowIndex], e);
    //                            debugStep = "Upload DependencyData";
    //                            UploadKDataBatchHandle(dataKey, batchHandle);
    //                            _SyncContext.CurrentDepen = null;
    //                        }

    //                    }
    //                }
    //            }
    //            Log.Info("End GetDependencyData for table " + tableName);
    //        }
    //        catch (Exception ex)
    //        {
    //            Log.Fatal("End GetDependencyData for table " + tableName + " with exception(" + debugStep + "):", ex);
    //            throw ex;
    //        }
    //        finally
    //        {
    //            _SyncContext.CurrentTable = null;
    //            _SyncContext.CurrentDepen = null;
    //        }
    //    }
    //    KDataBatchHandle SelectDependencyData(DependencyTable childrenTable, DataRowView currentRow, DbChangesSelectedEventArgs e)
    //    {
    //        Log.InfoFormat(" Select dependency rows of table {0} in table {1}", _SyncContext.CurrentTable.TableName, childrenTable.TableName);

    //        using (SqlCommand command = new SqlCommand(childrenTable.SelectRowCommand, Connection, Transaction))
    //        {
    //            command.CommandType = CommandType.StoredProcedure;
    //            command.Parameters.AddRange(
    //                SqlHelperParameterCache.GetSpParameterSet(CommonVariable.SqlConnectionString,
    //                        command.CommandText)
    //                );
    //            KeeperSyncUtility.AssignParameterValues(command, currentRow, DbSyncStage.SelectingChanges, Context);
    //            using (SqlDataReader reader = command.ExecuteReader())
    //            {
    //                KDataBatchHandle batchHandle = new KDataBatchHandle();
    //                batchHandle.BatchSize = _SyncContext.CurrentScope.BatchSize;
    //                batchHandle.Load(reader, childrenTable.TableName);
    //                return batchHandle;
    //            }
    //        }
    //    }
    //    void UploadKDataBatchHandle(string key, KDataBatchHandle batchHandle)
    //    {
    //        if (_SyncContext.Position == SyncProviderPosition.Local)
    //        {
    //            //Proxy to upload
    //            if (Proxy == null)
    //            {
    //                throw new Exception("Proxy is null");
    //            }
    //            Log.Info("Upload KDataBatchHandle using Proxy");
    //            Proxy.UploadDependencyBatchInfo(key, batchHandle.CloneWithoutData());
    //            for (int i = 1; i <= batchHandle.TotalBatch; i++)
    //            {
    //                Log.InfoFormat("Upload DataBatch {0} of {1}", i, batchHandle.TotalBatch);
    //                Proxy.UploadDependencyData(key, batchHandle.AllBatch[i]);
    //            }
    //        }
    //        else
    //        {
    //            Log.Info("Save KDataBatchHandle for client download");
    //            if (!DownloadedDependencyData.ContainsKey(key))
    //            {
    //                DownloadedDependencyData.Add(key, batchHandle);
    //                for (int i = 1; i <= batchHandle.TotalBatch; i++)
    //                {
    //                    KDataBatch data = batchHandle.AllBatch[i];
    //                    data.BatchFile = key.ToString() + "_IDX" + data.CurrentIndex.ToString() + ".xml";
    //                    data.Data.WriteXml(_Provider.BatchingDirectory+ "\\" + data.BatchFile);
    //                    data.Data.Clear();
    //                    data.Data.AcceptChanges();
    //                }

    //            }
    //            else
    //                Log.WarnFormat("DownloadedDependencyData has exists key={0} ==> Skipped", key);
    //        }
    //    }
    //}
}
